#pragma once

#include "Sock.hpp"
#include <functional>
#include <pthread.h>
#include <vector>

typedef std::function<void(int)> func_t;
namespace nets_tcpserver
{
    class TcpServer;
    class ThreadData
    {

    public:
        ThreadData(int sock, TcpServer* server):_sock(sock),_server(server)
        {}
        ~ThreadData()
        {}
    public:
        int _sock;
        TcpServer* _server;
    };
    class TcpServer
    {
    private:
        static void *ThreadRoutine(void *args)
        {
            pthread_detach(pthread_self()); // 挂起不需要等待
            ThreadData* td = static_cast<ThreadData*>(args);
            td->_server->Excute(td->_sock);
            close(td->_sock);
            return nullptr;
        }

    public:
        TcpServer(const uint16_t &port, const std::string &ip = "0.0.0.0")
        {
            _listensock = _sock.Socket();
            _sock.Bind(_listensock, port, ip);
            _sock.Listen(_listensock);
        }

        void BindServer(func_t func) { _func.push_back(func); }
        
        void Excute(int sock)
        {
            for(const auto& f : _func)
            {
                f(sock);
            }
        }

        void Start()
        {
            while (true)
            {
                std::string Clientip;
                uint16_t Clientport;
                int sock = _sock.Accept(_listensock, &Clientip, &Clientport);
                if (sock == -1)
                    continue;
                logMessage(NORMAL, "create new link succes, sock:%d\n", sock);
                pthread_t pid;
                ThreadData* td = new ThreadData(sock,this);
                pthread_create(&pid, nullptr, ThreadRoutine, td);
            }
        }
        ~TcpServer()
        {
              if (_listensock >= 0)
                close(_listensock);
        }
    private:
        int _listensock;
        Sock _sock;
        std::vector<func_t> _func;
    };
}